/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package probability;
import java.util.concurrent.*;
import java.util.*;
import util.*;
import net.*;

/**
 *
 * @author antonio
 */

/**
 * Class: _LocatorBayesian_
 * Usage: Class _TheCubix_ | metodo main()
 *
 * _LocatorBayesian_ è un Thread che si occupa di deaccodare oggetti della classe
 * _ProbabilityPosition_ dalla coda globale _QueuePointsPosition_
 * Per ogni oggetto _ProbabilityPosition_ estratto richiama il Thread
 * _WorkerLocatorBayesian_ che fa il lavoro sporco per lui.
 *
 * Class: _WorkerLocatorBayesian_
 * Usage: Class _LocatorBayesian_ | metodo run()
 *
 * _WorkerLocatorBayesian_ riceve, da _LocatorBayesian_, un oggetto tipo
 * _ProbabilityPosition_ contenente le info per calcolare la posizione corrente
 *
 * _WorkerLocatorBayesian_ in particolare deve:
 *
 * - 1 - a partire dall' oggetto _ProbabilityPosition_ costruire, per ogni punto
 *       candidato, un oggetto _TotalInfoPointPosition_
 *
 *      In generale infatti i segnali contenuti in un oggetto _ProbabilityPosition_
 *      sono divisi (oggetti _AccessPoint_) in base al mac dal quale si sono rilevati
 *      quei segnali. Si deve quindi per ogni punto candidato controllare tutti i mac
 *      degli oggetti AccessPoint. Se questi mac si trovano anche nella mappa di TRAI-
 *      -NING del punto candidato sommare i segnali e creare un oggetto:
 *      _TotalInfoPointPosition_ che conterrà tutti i segnali sniffatida NS provenienti
 *       dai mac che si trovano anche nella mappa di TRAINING del punto, cioè che erano
 *      già noti al punto.
 *
 *      _TotalInfoPointPosition_ quindi è l'oggetto che contiene le info finali per un
 *      punto, necessarie per calcolare la probabilità del punto candidato di essere
 *      quello che meglio approssima la posizione corrente
 *
 * - 2 - Inserire nel Vector totalInfoPoint tutti gli oggetti _TotalInfoPointPosition_ .
 *       Il Vector totalInfoPoint verrà elaborato da un oggetto _ModifierPositin_
 *       che in base alle info degli oggetti _TotalInfoPointPosition_ eleggerà il punto che
 *       rappresenta la posizione corrente
 *
 */
public class LocatorBayesian extends Thread{

    private LinkedBlockingQueue queuePoints;

    public LocatorBayesian()
    {
        this.queuePoints = QueuePointsPosition.queue;
        //il locator si autoavvia.
        this.start();
    }

    public void run()
    {
        while(true)
        {
            ProbabilityPosition event = (ProbabilityPosition)this.queuePoints.poll();
            if(event != null)
            {
                WorkerLocatorBayesian worker = new WorkerLocatorBayesian(event);
                Thread t = new Thread(worker);
                t.start();
            }
            else
            {
                //che faccio gli metto una sleep()??
                this.yield();
                continue;
            }
        }

    }
}

class WorkerLocatorBayesian implements Runnable{

    private ProbabilityPosition event;
    private Vector totalInfoPoint;

    public WorkerLocatorBayesian(ProbabilityPosition event)
    {
        this.event = event;
        this.totalInfoPoint = new Vector();
    }

    public void run()
    {
        try{
        Vector candidates = this.event.getPoints();  //punti candidati per la posizione corrente
        

        Vector accessPointSniffed = this.event.getInfoPosition();  //info degli AP rilevati nella posiione corrente

        for(int i=0; i<candidates.size(); i++)
        {
            Vector mac = new Vector();
            String point = (String)candidates.elementAt(i);  //estraggo il primo punto candidato

            TotalInfoPointPosition totalForOnePoint = new TotalInfoPointPosition(point);
            //contiene le info di un punto candidato, con tutti i segnali (merge) dei mac rilevati


            ReaderPointsFile readerpoint = new ReaderPointsFile(point);
            //carico i mac (con ripsettivi segnali) del punto candidato


            Vector apPoint = readerpoint.read();


             //controllo quali AP di quelli sniffati si trovano nei punti candidati
            //della mappa, se il mac rilevato da NS si trova nella mappa del punto
           //(cioè è noto che nel punto nella fase di TRAINING si rilevava il mac)
          //aggiungo i segnali sniffati da NS da quel mac nel campo signal dell'
         //oggetto TotalInfoPointPosition che rappresenta le info del punto candidato.
            for(int j=0; j<accessPointSniffed.size(); j++)
            {

                AccessPoint apSniffed = (AccessPoint)accessPointSniffed.elementAt(j);

                for(int k=0; k<apPoint.size(); k++)  //trovo il corrispondente del mac sniffato nella mappa del punto
                {
                    String macPoint = ( (AccessPoint)apPoint.elementAt(k) ).getMac();
                    
                    if(macPoint.equals(apSniffed.getMac()))  //se il mac del punto coincide col mac sniffato faccio il merge
                    {
                            mac.add(macPoint);
                            MergeInfoPointPosition merger = new MergeInfoPointPosition(macPoint, apSniffed, totalForOnePoint);
                            totalForOnePoint = merger.calculation();
                            continue;
                    }
                }
            }
            totalForOnePoint.setMac(mac);
        //per un punto candidato avrò creato un oggetto totalForOnePoint di classe
       //TotalInfoPointPosition che contiene il nome del punto candidato,
      //tutti i segnali di tutti i mac rilevati da NS che si trovano anche nella mappa del putno, cioè erano noti in fase di TRAINING,
     //il totale di tutti questi segnali

            System.out.println("Locaotr Bayesian, punto: " + totalForOnePoint.getPoint());
            for(int c=0; c<totalForOnePoint.getMac().size(); c++)
            {
                String m = (String)totalForOnePoint.getMac().elementAt(c);
                System.out.print("|" + m + "|");
            }
            System.out.println();

            System.out.println("signal: ");
            for(int e=0; e<100; e++)
                System.out.print("|" + totalForOnePoint.getSignal(e).intValue() + "|");
            System.out.println();

            System.out.println("total: " + totalForOnePoint.getTotal().intValue());

            System.out.println();
            
            this.totalInfoPoint.add(totalForOnePoint);
        }

        //alla fine del ciclo, avrà riempito il Vector totalInfoPoint
        //con tutti gli oggetti di classe TotalInfoPointPosition
        //che rappresentano le info totali per un punto candidato.
        //Quindi in totalInfoPoint avrò tutte le info per tutti i punti
        //candidati, info da utilizzare per eleggere il punto che
        //più approssima la posizione corrente dell'utente.
        
        ModifierPosition modifier = new ModifierPosition(this.totalInfoPoint);
        
        }catch(Exception e)
        {
            e.printStackTrace();
        }
    }
}
